﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Vowei.Core.Models;
using System.Data.Entity.Infrastructure;
using Vowei.Core;
using System.Diagnostics;
using Vowei.Data.Models;
using System.Data.Entity.Database;

namespace Vowei.Data
{
    public static class BuiltinSettingInitializer
    {
        public static void Feed(VoweiContext context)
        {
            FeedPermissions(context);
            FeedPermissionSet(context);
        }

        private static void FeedPermissions(VoweiContext context)
        {
            var fields = typeof(Constants.Permission.Read).GetFields();

            foreach (var field in fields)
            {
                var value = field.GetValue(null) as string;
                Debug.Assert(value != null);
                context.Permissions.Add(new Permission()
                {
                    Title = value
                });
            }

            fields = typeof(Constants.Permission.Write).GetFields();

            foreach (var field in fields)
            {
                var value = field.GetValue(null) as string;
                Debug.Assert(value != null);
                context.Permissions.Add(new Permission()
                {
                    Title = value
                });
            }

            context.SaveChanges();
        }

        private static void FeedPermissionSet(VoweiContext context)
        {
            #region 项目管理权限集
            var pset = new PermissionSet()
            {
                Title = Constants.BuiltIn.PermissionSet.ManageProjectPermissionSet
            };

            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Project));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Milestone));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Requirement));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Task));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Risk));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Bug));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Comment));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.ChangeSet));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Comment));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.MeetingRequest));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Permission));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.PermissionSet));

            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Project));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Milestone));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Requirement));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Task));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Risk));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Bug));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.MeetingRequest));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Permission));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.PermissionSet));

            context.PermissionSet.Add(pset);
            #endregion

            #region 浏览项目状态权限集
            pset = new PermissionSet()
            {
                Title = Constants.BuiltIn.PermissionSet.ProjectViewerPermissionSet
            };

            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Project));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Milestone));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Requirement));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Task));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Risk));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Bug));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Comment));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.ChangeSet));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Comment));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.MeetingRequest));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Permission));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.PermissionSet));

            context.PermissionSet.Add(pset);
            #endregion

            #region 项目概览权限集
            pset = new PermissionSet()
            {
                Title = "项目概览"
            };

            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Project));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Requirement));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Risk));

            context.PermissionSet.Add(pset);
            #endregion

            #region 项目成员权限集
            pset = new PermissionSet()
            {
                Title = Constants.BuiltIn.PermissionSet.ProjectMemeberPermissionSet
            };

            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Project));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Milestone));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Requirement));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Task));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Risk));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Bug));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Comment));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.ChangeSet));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Comment));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.MeetingRequest));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.Permission));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Read.PermissionSet));

            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Task));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Risk));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.Bug));
            pset.Children.Add(context.Permissions.First(
                p => p.Title == Constants.Permission.Write.MeetingRequest));

            context.PermissionSet.Add(pset);
            #endregion

            context.SaveChanges();
        }

    }

#if TEST
    public static class VirtualContextInitializer
    {
        public static readonly string[,] MsfMilestoneTitles = new string[,] {
            {"Vision/Scope Approved",""},
            {"", "Core Team Organized" },
            {"", "Vision/Scope Drafted" },
            {"Project Plans Approved",""},
            {"", "Technology Validatoin"},
            {"", "Functional Specification Baselined"},
            {"", "Master Plan Baselined"},
            {"", "Master Schedule Baselined"},
            {"", "Development and Test Environment Set Up"},
            {"Scope Complete", "" },
            {"", "Proof of Concept Complete"},
            {"", "Internal Build n Complete, Internal build n+1 Complete"},
            {"Release Readiness Approved", ""},
            {"", "Bug Convergence" },
            {"", "Zero Bug Bounce" },
            {"", "Release Candidates" },
            {"", "Pre-Production Test Complete"},
            {"", "User Acceptance Testing Complete"},
            {"", "Pilot Complete"},
            {"Deployment Complete", ""},
            {"", "Core Components Deployed" },
            {"", "Site Deployments Complete Interim Milestone"},
            {"", "Deployment Stable Interim Miletone"}
        };

        public static void Feed(VoweiContext context)
        {
            BuiltinSettingInitializer.Feed(context);

            var user = Constants.BuiltIn.Users.Administrator;

            #region MSF项目类型
            var project = new Project()
            {
                Title = "MSF Project",
                Owner = user,
                StartDate = DateTime.Now
            };
            context.Projects.Add(project);
            context.SaveChanges();

            Milestone prevMajor = null;
            for (int i = 0; i < MsfMilestoneTitles.GetLength(0); ++i)
            {
                var msfMilestone = new Milestone()
                {
                    DueDate = project.StartDate + TimeSpan.FromDays(i * 30)
                };
                context.Milestones.Add(msfMilestone);

                // 小里程碑 - Interim Milestone
                if (string.IsNullOrEmpty(MsfMilestoneTitles[i, 0]))
                {
                    msfMilestone.Title = MsfMilestoneTitles[i, 1];
                    prevMajor.AddChild(msfMilestone);
                    context.SaveChanges();
                }
                else
                {
                    msfMilestone.Title = MsfMilestoneTitles[i, 0];
                    project.AddChild(msfMilestone);
                    prevMajor = msfMilestone;
                    context.SaveChanges();
                }
            }

            context.SaveChanges();
            #endregion

            #region Scrum项目类型
            project = new Project()
            {
                Title = "Scrum Project",
                Owner = user,
                StartDate = DateTime.Now
            };
            context.Projects.Add(project);
            context.SaveChanges();
            
            for (int i = 1; i < 13; ++i)
            {
                var sprint = new Milestone()
                {
                    Title = string.Format("Spring {0}", i),
                    DueDate = project.StartDate + TimeSpan.FromDays(i * 30)
                };
                context.Milestones.Add(sprint);
                context.SaveChanges();
            }
            #endregion

            #region Svn项目
            project = new Project()
            {
                Title = "Svn测试项目",
                DueDate = new DateTime(2011, 1, 31),
                Owner = user,
                StartDate = new DateTime(2010, 12, 1),
                ScmType = Project.SupportedScm.Svn,
                ScmUrl = "http://shiyimin:88/svn/vowei/"
            };
            context.Projects.Add(project);

            project = new Project()
            {
                Title = "不由yimin_shi@hotmail.com负责的项目",
                Owner = "otherpeoople@test.com",
                StartDate = DateTime.Now,
                DueDate = DateTime.Now + TimeSpan.FromDays(30)
            };
            context.Projects.Add(project);
            context.SaveChanges();
            #endregion

            #region CMMI 项目类型
            project = new Project()
            {
                Title = "CMMI 项目",
                Owner = user
            };
            context.Projects.Add(project);
            context.SaveChanges();

            var titles = new string[] 
            {
                "Performed Process",
                "Managed Process",
                "Defined Process",
                "Quantitative Managed Process",
                "Optimizing Process"
            };

            foreach (var title in titles)
            {
                var item = context.Create<Milestone>(title);
                project.AddChild(item);
                context.Milestones.Add(item);
            }
            context.SaveChanges();

            var milestone = project.Children.ElementAt(1);
            titles = new string[] 
            {
                "Establish an Organizational Policy",
                "Plan the Process",
                "Provide Resources",
                "Assign Responsibility",
                "Train People",
                "Manage Configuration",
                "Identify and Involve Relevant Stackholders",
                "Monitor and Control the Process",
                "Objectively Evaluate Adherence",
                "Review Status with Higher Level Management"
            };
            var requirements = CreateRequirementHelper(context, titles, milestone);
            // context.SaveChanges();

            var requirement = requirements[1];
            // 跟需求相关的任务
            titles = new string[]
            {
                "Process description",
                "Standards and requirements for the work products and services of the process",
                "Specific objectives for the performance of the process (e.g., quality, time scale, cycle time, use of resources)",
                "Dependencies among the activities, work products, and services of the process",
                "Resources (e.g., funding, people, tools) needed to perform the process",
                "Assignment of responsibility and authority",
                "Training needed for performing and supporting the process",
                "Work products to be controlled and the level of control to be applied",
                "Measurement requirements to provide insight into the performance of the process, its work products, and its services",
                "Involvement of identified stakeholders",
                "Activities for monitoring and controlling the process",
                "Objective evaluation activities of the process",
                "Management review activities for the process and the work products"
            };
            CreateTasksInRequirement(context, titles, requirement);
            context.SaveChanges();
            #endregion

            #region 在测试过程中不会变更的测试项目
            project = new Project()
            {
                Title = "在测试过程中不会变更的测试项目",
                Owner = user
            };
            project.ID = UnchangedProjectId;
            context.Projects.Add(project);

            titles = new string[] 
            {
                "Performed Process",
                "Managed Process",
                "Defined Process",
                "Quantitative Managed Process",
                "Optimizing Process"
            };

            foreach (var title in titles)
            {
                var item = context.Create<Milestone>(title);
                project.AddChild(item);
                context.Milestones.Add(item);
            }
            context.SaveChanges();

            milestone = project.Children.ElementAt(1);
            titles = new string[] 
            {
                "Establish an Organizational Policy",
                "Plan the Process",
                "Provide Resources",
                "Assign Responsibility",
                "Train People",
                "Manage Configuration",
                "Identify and Involve Relevant Stackholders",
                "Monitor and Control the Process",
                "Objectively Evaluate Adherence",
                "Review Status with Higher Level Management"
            };
            requirements = CreateRequirementHelper(context, titles, milestone);

            requirement = requirements[1];
            // 跟需求相关的任务
            titles = new string[]
            {
                "Process description",
                "Standards and requirements for the work products and services of the process",
                "Specific objectives for the performance of the process (e.g., quality, time scale, cycle time, use of resources)",
                "Dependencies among the activities, work products, and services of the process",
                "Resources (e.g., funding, people, tools) needed to perform the process",
                "Assignment of responsibility and authority",
                "Training needed for performing and supporting the process",
                "Work products to be controlled and the level of control to be applied",
                "Measurement requirements to provide insight into the performance of the process, its work products, and its services",
                "Involvement of identified stakeholders",
                "Activities for monitoring and controlling the process",
                "Objective evaluation activities of the process",
                "Management review activities for the process and the work products"
            };
            CreateTasksInRequirement(context, titles, requirement);
            context.SaveChanges();
            #endregion

            #region Add Comment [Comment Samples]
            var comment = new Comment()
            {
                User = user,
                CommentDate = DateTime.Now,
                // 用户输入的字符串应该是下面这个格式
                //     "签入[f16569d55800]以修复任务#7"
                //
                // 网站自动替换成下面这个格式
                //     其中SCM的链接是从Project.ScmUrl里面获取的
                //
                // 后面要做的工作是
                // TODO: 编写一个Mercurial或SVN客户端，自动生成上面的字符串
                Text = "签入<a href='https://hg01.codeplex.com/vowei/rev/f16569d55800'>f16569d55800</a>以修复任务<a href='/Task/Details/8'>8</a>"
            };
            var task = context.Tasks.Where(t => t.Title == "Process description").First();
            task.AddComment(comment);
            context.Comments.Add(comment);
            #endregion

            context.SaveChanges();
        }
        private static void CreateTasksInRequirement(VoweiContext context, string[] titles, Requirement requirement)
        {
            foreach (var title in titles)
            {
                var item = context.Create<Task>(title);
                item.AssignedTo = Constants.BuiltIn.Users.Administrator;
                context.Tasks.Add(item);
                requirement.AddChild(item);
            }
        }
            
        private static Requirement[] CreateRequirementHelper(VoweiContext context, string[] titles, Milestone parent)
        {
            var results = new List<Requirement>();

            foreach (var title in titles)
            {
                var item = context.Create<Requirement>(title);
                results.Add(item);
                item.AssignedTo = Constants.BuiltIn.Users.Administrator;
                item.Milestone = parent;

                context.Requirements.Add(item);
            }

            return results.ToArray();
        }

        public static string MsfProjectTitle { get { return "MSF Project"; } }

        public static string MsfSubMilestoneTitle { get { return "Vision/Scope Drafted"; } }

        public static string ScrumSprintTitle { get { return "Spring 1"; } }

        private static Guid _UnchangedProjectId = new Guid("00000000-0000-0000-0000-000000000001");
        public static Guid UnchangedProjectId { get { return _UnchangedProjectId; } }
    }
#endif

    public class VoweiContextTestInitializer : DropCreateDatabaseAlways<VoweiContext>
    {
        protected override void Seed(VoweiContext context)
        {
            VirtualContextInitializer.Feed(context);
            base.Seed(context);
        }
    }

    public class VoweiContextInitializer : DropCreateDatabaseAlways<VoweiContext>
    {
        protected override void Seed(VoweiContext context)
        {
            BuiltinSettingInitializer.Feed(context);
            base.Seed(context);
        }
    }
}
